/**
 * Copyright 2015 iMeht studio(http://www.imeth.cn--). All rights reserved.
 * Encoding UTF-8
 * Version: 1.0
 * Date: 2015-2-4
 * History:	
 */

package cn.imeth.eclipse.concurrency;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 这是一个学习并发的练习
 * 
 * @author 戴文龙 (daiwenlong@icifit.com)
 * @version Revision: 1.0.0 Date: 2015-2-4
 */
public class Main {

	public static void main(String[] args) {

		testThreadPool();
		decollator();
		
		decollator();
		decollator();
		testExchanger();
		decollator();
		decollator();
		decollator();
	}

	/**
	 * <p>
	 * 线程池可以降低创建线程的开销。
	 * </p>
	 * <li>线程池在线程执行结束后进行线程的是回收操作，而不是真正的销毁线程。</li> <li>在线程中完成生产一个随机整数，并随机整数加入到队列中
	 * </li>
	 * 
	 * @author 戴文龙 (daiwenlong@icifit.com)
	 * @version Revision: 1.0.0 Date: 2015-2-4
	 */
	private static void testThreadPool() {
		int count = 200000;
		useThreadPool(count);
		useThread(count);
	}

	private static void useThread(int count) {
		long startTime = System.currentTimeMillis();
		final List<Integer> data = new LinkedList<>();
		final Random random = new Random();
		
		for (int i = 0; i < count; i++) {
			Thread thread = new Thread(){
				
				@Override
				public void run() {
					data.add(random.nextInt());
				};
			};
			
			thread.start();
			
			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		System.out.println("Time" + (System.currentTimeMillis() - startTime));
		System.out.println(data.size());
	}

	private static void useThreadPool(int count) {
		long startTime = System.currentTimeMillis();
		final List<Integer> data = new LinkedList<>();
		final Random random = new Random();
		ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(count));

		for (int i = 0; i < count; i++) {
			executor.execute(new Runnable() {

				@Override
				public void run() {
					data.add(random.nextInt());
				}
			});
		}

		executor.shutdown();

		try {
			executor.awaitTermination(1, TimeUnit.DAYS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("Time" + (System.currentTimeMillis() - startTime));
		System.out.println(data.size());

	}

	/**
	 * <p>
	 * Exchanger 是用于两个线程之间进行数据交换。
	 * </p>
	 * <li>线程会阻塞Exchanger的exchane方法上，直到另外一个线程也到了同一个Exchanger的exchange方法时,二者进行交换,
	 * 然后两个线程会继续执行自身相关的代码</li> <li>
	 * 线程1和线程2，都有一个队列，他们的队列中分别写入数据，然后线程交换队列，打印队列数据后结束</li>
	 * 
	 * 
	 * @author 戴文龙 (daiwenlong@icifit.com)
	 * @version Revision: 1.0.0 Date: 2015-2-4
	 */
	private static void testExchanger() {
		final Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();

		new Thread() {

			@Override
			public void run() {
				List<Integer> data = new ArrayList<Integer>();
				data.add(1);
				data.add(2);

				System.out.println("Thread 1 Before:" + data);

				try {
					data = exchanger.exchange(data);
				} catch (Exception e) {
					e.printStackTrace();
				}

				System.out.println("Thread 1 After :" + data);

			};
		}.start();

		new Thread() {

			@Override
			public void run() {
				List<Integer> data = new ArrayList<Integer>();
				data.add(4);
				data.add(5);
				System.out.println("Thread 2 Before:" + data);

				try {
					data = exchanger.exchange(data);
				} catch (Exception e) {
					e.printStackTrace();
				}

				System.out.println("Thread 2 :" + data);

			};
		}.start();
	}

	private static void decollator() {
		System.out.println("\n=======================\n");
	}

}
